package ru.zombator.taskman.client.ui;

import java.util.concurrent.TimeoutException;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

import ru.zombator.taskman.client.actions.CreateProjectAction;
import ru.zombator.taskman.client.actions.JoinProjectAction;
import ru.zombator.taskman.client.query.ClientFactory;
import ru.zombator.taskman.client.query.ClientInitException;
import ru.zombator.taskman.core.domain.IManager;
import ru.zombator.taskman.core.domain.IPerson;
import ru.zombator.taskman.core.query.IClient;
import ru.zombator.taskman.core.query.ITypedPacket;
import ru.zombator.taskman.core.query.TypedPacket;
import ru.zombator.taskman.core.query.payload.ErrorResponse;
import ru.zombator.taskman.core.query.payload.WhoAmIRequest;
import ru.zombator.taskman.core.query.payload.WhoAmIResponse;
import ru.zombator.taskman.core.ui.ChooseProtocolDialog;

/**
 * Главное окно клиентского приложения
 * 
 * @author nvamelichev
 * 
 */
public class ClientWindow extends ApplicationWindow {
	private IClient clientInstance;
	private IPerson me;

	public ClientWindow(Shell parentShell) {
		super(parentShell);
		addMenuBar();
	}

	public IClient getClient() {
		return clientInstance;
	}

	public IPerson getTheUser() {
		return me;
	}

	@Override
	protected MenuManager createMenuManager() {
		MenuManager mgr = new MenuManager("");
		MenuManager file = new MenuManager("&Файл");
		ActionContributionItem fileExit = new ActionContributionItem(
				new Action("В&ыход") {
					@Override
					public void run() {
						close();
					}
				});
		file.add(fileExit);
		mgr.add(file);

		MenuManager projects = new MenuManager("&Проекты");
		ActionContributionItem createProject = new ActionContributionItem(
				new CreateProjectAction(this));
		ActionContributionItem joinProject = new ActionContributionItem(
		        new JoinProjectAction(this));
		projects.add(createProject);
		projects.add(joinProject);
		mgr.add(projects);

		return mgr;
	}

	@Override
	public void create() {
		super.create();
	}

	private void customizeForUserType() {
		getShell().setText(
				String.format("Клиентское приложение - %s %s [%s]",
						(me instanceof IManager ? "менеджер" : "исполнитель"),
						me.getName(), me.getIpAddress()));
	}

	@Override
	public int open() {
		// выбор протокола
		ChooseProtocolDialog dlg = new ChooseProtocolDialog(null);
		if (dlg.open() == OK) {
			try {
				super.create();
				clientInstance = ClientFactory.createClient(dlg.getProtocol());
				ITypedPacket whoAmIPkt = clientInstance
						.sendPacket(new TypedPacket(new WhoAmIRequest()));
				Object response = whoAmIPkt.asObject();
				if (response instanceof ErrorResponse) {
					throw new Exception(((ErrorResponse) response).getMessage());
				}
				WhoAmIResponse whoAmI = (WhoAmIResponse) response;
				this.me = whoAmI.getWho();

				if (this.me == null) {
					MessageDialog
							.openWarning(
									getShell(),
									"Внимание",
									"Пользователя с вашим IP-адресом в базе данных не зарегистрировано.\n"
											+ "Обратитесь к системному администратору за помощью.");
					close();
					System.exit(-1);
				}

				customizeForUserType();

				return super.open();
			} catch (ClientInitException e) {
				MessageDialog
						.openError(
								getShell(),
								"Ошибка соединения",
								"Не удалось запустить клиентское приложение.\n"
										+ "Проверьте, что доступен сервер, а на нем открыты порты 1099, 3333 и 5555.\n"
										+ "Для протоколов RMI и CORBA/IIOP проверьте, что работает сервис именования.");
				e.printStackTrace();
			} catch (TimeoutException e) {
				e.printStackTrace();
				MessageDialog
						.openError(
								getShell(),
								"Ошибка соединения",
								"Истекло время ожидания ответа на запрос 'получить текущего пользователя'.\n"
										+ "Перезапустите клиентское приложение и попробуйте еще раз.");
			} catch (Exception e) {
				e.printStackTrace();
				MessageDialog
						.openError(
								getShell(),
								"Ошибка соединения",
								"Не удалось получить ответ на запрос 'получить текущего пользователя':\n"
										+ e.getMessage()
										+ "\n"
										+ "Перезапустите клиентское приложение и попробуйте еще раз.");
			}
		}
		close();
		System.exit(-1);
		return 0;
	}

	@Override
	public boolean close() {
		if (clientInstance != null)
			clientInstance.dispose();
		return super.close();
	}

	@Override
	protected Control createContents(Composite parent) {
		Composite inner = new Composite(parent, SWT.NONE);
		inner.setLayout(new FillLayout(SWT.HORIZONTAL));

		return inner;
	}

	@Override
	protected Point getInitialSize() {
		return new Point(1000, 600);
	}
}
